package com.uto.backend;

import java.util.HashMap;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.GpsStatus.Listener;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.uto.UTO;
import com.uto.User;
import com.uto.backend.interfaces.IAppManager;
import com.uto.backend.interfaces.IServerResponse;
import com.uto.frontend.interfaces.IServiceListener;

public class AppService extends Service{


	//The player registered to the game
	private User user;

	//The game currently being played
	private Object game;

	//The manager in charge of location changes
	private LocationManager locationManager;

	//tag for logging
	private final String TAG = "com.uto.backend.AppService"; 
	
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}
	
	
	@Override
	public void onCreate(){
		super.onCreate();
		Log.d(TAG,"on create begin...");
		//setup the location listener.
		locationManager =(LocationManager) getSystemService(Context.LOCATION_SERVICE);
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 5, new LocationUpdateHandler());

	}

	@Override
	public IBinder onBind(Intent intent) {
		return binder;
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.d(TAG,"on start begin...");
		super.onStart(intent, startId);
		intent.getStringExtra("CALLER");
		//get the current user
		if (user==null){
			SharedPreferences settings = getSharedPreferences(UTO.USER_FILE, 0);
			if (settings!=null){
				String username = settings.getString("username", null);
				Log.d(TAG,"Shared Prefernces username: "+username);
				String password = settings.getString("password", null);
				Log.d(TAG,"Shared Prefernces password: "+password);
				String firstName = settings.getString("firstName", null);
				Log.d(TAG,"Shared Prefernces first Name: "+firstName);
				String lastName = settings.getString("lastName", null);
				Log.d(TAG,"Shared Prefernces last Name: "+lastName);
				int money = settings.getInt("money", 0);
				Log.d(TAG,"Shared Prefernces money: "+money);
				String streets = settings.getString("streets", null);
				Log.d(TAG,"Shared Prefernces streets: "+streets);
				user = new User(username , password ,firstName , lastName, money, streets);
			}
			else {
				Log.d(TAG,"Shared Prefernces is null.");
			}
		}
		else {
			Log.d(TAG,"user is not null "+user.getUsername());
		}

		//setup the location listener.
		if (locationManager==null){
			locationManager =(LocationManager) getSystemService(Context.LOCATION_SERVICE);
			locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 5, new LocationUpdateHandler());

		}
	}

	// this inner class is the intent receiver that receives notifcations
	// from the location provider about position updates.
	public class LocationUpdateHandler implements LocationListener {

		public void onLocationChanged(Location loc) {
			try {
				binder.locationChanged(loc.getLatitude(), loc.getLongitude());
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		public void onProviderDisabled(String provider) {}

		public void onProviderEnabled(String provider) {}

		public void onStatusChanged(String provider, int status, Bundle extras) {}

	}

	private final IAppManager.Stub binder = new IAppManager.Stub (){


		public void login(User user, IServiceListener listener)throws RemoteException {
			AppService.this.user = user;

			//build a Map with the needed data, and send it to the request builder
			Map<String,String> data = new HashMap<String,String>();
			data.put("userName", user.getUsername());
			data.put("password",  user.getUsername());
			LoginListener ll = new LoginListener();
			ll.setListner(listener);
			new HttpRequestBuilder().sendRequest(ll, HttpConnnectionThread.GET , HttpRequestBuilder.TYPE_LOGIN, data,null);
		}


		public void getAviliableGames(IServiceListener listener)
		 {
//			//get the latest known location
//			Location curLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//
//			if (curLocation==null)
//			{
//				//if the location is null, send an error message. The user should be told to switch on his gps or move a little
//				try {
//					listener.handleMessage(null);
//				} catch (RemoteException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
//			}
//
//			//build a Map with the needed data, and send it to the request builder
//			Map<String,String> data = new HashMap<String,String>();
//			data.put("lat", ""+curLocation.getLatitude());
//			data.put("lng", ""+curLocation.getLongitude());
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_GET_AVILIABLE_GAMES, null ,null);

		}


		public void getAviliableMaps(IServiceListener listener)
		throws RemoteException {

			//get the latest known location
			Location curLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);


			if (curLocation==null)
			{
				//if the location is null, send an error message. The user should be told to switch on his gps or move a little
				listener.handleMessage(null);
			}

			//build a Map with the needed data, and send it to the request builder
			Map<String,String> data = new HashMap<String,String>();
			data.put("lat", ""+curLocation.getLatitude());
			data.put("lng", ""+curLocation.getLongitude());
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_GET_AVILIABLE_MAPS, data,null);
		}


		public void register(User user, IServiceListener listener)
		throws RemoteException {
			//build a Map with the needed data, and send it to the request builder
			Map<String,String> data = new HashMap<String,String>();
			data.put("userName", user.getUsername());
			data.put("password",  user.getUsername());
			data.put("firstName", user.getFirstName());
			data.put("lastName", user.getLastName());
			new HttpRequestBuilder().sendRequest(listener,HttpConnnectionThread.GET , HttpRequestBuilder.TYPE_REGISTER, data ,null);
		}



		public void playerAction(String actionType, String properties , IServiceListener listener)
		throws RemoteException {
			//build a Map with the needed data, and send it to the request builder
			Map<String,String> data = new HashMap<String,String>();
			data.put("userName", user.getUsername());
			data.put("password",  user.getUsername());
			data.put("action" , actionType);
			data.put("porperties" , properties);
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_PLAYER_ACTION, data,null);
		}



		public void locationChanged(double lat, double lng) throws RemoteException {

			//build a Map with the needed data, and send it to the request builder
			Map<String,String> data = new HashMap<String,String>();
			data.put("lat", ""+lat);
			data.put("lng", ""+lng);
			if (user==null){
				SharedPreferences settings = getSharedPreferences(UTO.USER_FILE, 0);
				if (settings!=null){
					String username = settings.getString("username", null);
					Log.d(TAG,"Shared Prefernces username: "+username);
					String password = settings.getString("password", null);
					Log.d(TAG,"Shared Prefernces password: "+password);
					String firstName = settings.getString("firstName", null);
					Log.d(TAG,"Shared Prefernces first Name: "+firstName);
					String lastName = settings.getString("lastName", null);
					Log.d(TAG,"Shared Prefernces last Name: "+lastName);
					int money = settings.getInt("money", 0);
					Log.d(TAG,"Shared Prefernces money: "+money);
					String streets = settings.getString("streets", null);
					Log.d(TAG,"Shared Prefernces streets: "+streets);
					user = new User(username , password ,firstName , lastName, money, streets);
				}
				else {
					Log.d(TAG,"Shared Prefernces is null.");
				}
			}
			else {
				Log.d(TAG,"user is not null "+user.getUsername());
			}
			data.put("userName", user.getUsername());
			Log.d(TAG, "userName is: "+user.getUsername());
			//the location changed response is handled locally, here in the appService
			new HttpRequestBuilder().sendRequest(locationMessageListener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_LOCATION_CHANGED, data,null);
		}


		public int getUserMoney() throws RemoteException {
			if (user!=null)
				return user.getMoney();

			return -1;
		}


		public String getUserStreets() throws RemoteException {
			if (user!=null)
				return user.getStreets();

			return null;
		}


		public void joinGame(IServiceListener listener , String gameId, String userName) throws RemoteException {

			Map<String,String> data = new HashMap<String,String>();
			data.put("gameKey", ""+gameId);
			data.put("userName", ""+userName);
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_JOIN_GAME, data,null);
			
		}


		public void startNewGame(IServiceListener listener , int numPlayers, int money,String userName)
		throws RemoteException {

			Map<String,String> data = new HashMap<String,String>();
			data.put("numOfPlayers", ""+numPlayers);
			data.put("initMoney", ""+money);
			data.put("userName", ""+userName);
			
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_START_NEW_GAME, data,null);
		}
		
		
		
		public void sellStreet(String userName,int street, IServiceListener listener)
		throws RemoteException {

			Map<String,String> data = new HashMap<String,String>();
			data.put("streetNum", ""+street);
			data.put("userName", ""+userName);
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_SELL_STREET, data,null);
		}
		
		
		public void updateGameData(String userName,IServiceListener listener)
		throws RemoteException {			
			Log.d("AppService", "Calling UpdateGameData");
			Map<String,String> data = new HashMap<String,String>();
			data.put("userName", ""+userName);
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_UPDATE_GAME_DATA,data,null);
		}
		
		public void gameRanking(String userName,IServiceListener listener)
		throws RemoteException {			
			Log.d("AppService", "Getting to server ranking");
			Map<String,String> data = new HashMap<String,String>();
			data.put("userName", ""+userName);
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_RANKING,data,null);
		}
		
		public void log(String userName,IServiceListener listener) {
			Log.d("AppService", "Getting to server log");
			Map<String,String> data = new HashMap<String,String>();
			data.put("userName", ""+userName);
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_LOG,data,null);
		}
		
		public void buy(String userName ,double lat ,double lng , IServiceListener listener) {
			Log.d(TAG, "calling to buy servlet");
			Map<String,String> data = new HashMap<String,String>();
			data.put("userName", ""+userName);
			data.put("lat", ""+lat);
			data.put("lng", ""+lng);			
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_BUY_STREET,data,null);
		}
		
		public void drawMap(String userName,IServiceListener listener){
			Log.d(TAG, "calling to drawMap servlet");
			Map<String,String> data = new HashMap<String,String>();
			data.put("userName", ""+userName);
			new HttpRequestBuilder().sendRequest(listener, HttpConnnectionThread.GET ,HttpRequestBuilder.TYPE_DRAW_MAP,data,null);
		}
		
		public void destroyService(){
			onDestroy();
			stopSelf();
		}
		
	};

	private class LoginListener extends IServiceListener.Stub {

		private IServiceListener listener;

		public void handleMessage(IServerResponse response) {
			if (user!=null){
				Integer money;
				try {

					money = (Integer)response.getData().get("money");
					user.setMoney(money.intValue());

					String streets = "";
					JSONArray arr = (JSONArray)response.getData().get("streets");
					for (int i=0; i<arr.length(); i++){
						String curStreet = arr.getString(i);
						streets += curStreet+ ",";						
					}
					user.setStreets(streets);

					response.getData().clear();
					response.getData().put("user", user);

					listener.handleMessage(response);
				} catch (Exception e) {
					Log.v(TAG, e.getMessage());
					e.printStackTrace();
				}
			}

		}

		public void setListner(IServiceListener listener) {
			this.listener = listener;

		}
	};

	private final IServiceListener.Stub locationMessageListener = new IServiceListener.Stub(){


		public void handleMessage(IServerResponse response) {
			// TODO Auto-generated method stub

		}
	};



}
